// Find dbghelp.dll (WindDbg installation directory)

// ----------------------------------------------------------------------------

#include "stdafx.h"

#include "DSymLoadDbgHelp.h"
#include "DSymLoadDbgHelpLocator.h"

// ----------------------------------------------------------------------------

namespace DSymLoad
{

// ----------------------------------------------------------------------------

namespace
{

// ----------------------------------------------------------------------------

const PCWSTR g_Versions[] = 
{
    L"10",      // Windows 10 Kits
    L"81",      // Windows 8.1 Kits
    L"",        // Windows 8 Kits
};

// ----------------------------------------------------------------------------

struct CRootDescritption
{
    PCWSTR m_wszKeyName;
    PCSTR m_szPathTail;

    CRootDescritption(PCWSTR wszKeyName, PCSTR szPathTail)
        : m_wszKeyName(wszKeyName), m_szPathTail(szPathTail)
    {
    }
};

const CRootDescritption g_Roots[] = 
{
    CRootDescritption(L"WindowsDebuggersRoot", ""),
    CRootDescritption(L"KitsRoot", "Debuggers")
};

// ----------------------------------------------------------------------------

}

// ----------------------------------------------------------------------------

CStringA FindDbgHelp()
{
    CRegKey hInstalledRoots;

    auto nErrorCode = 
        hInstalledRoots.Open(
                HKEY_LOCAL_MACHINE,
                L"SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots",
                KEY_QUERY_VALUE);
    if (ERROR_SUCCESS != nErrorCode)
    {
        _ASSERT(ERROR_FILE_NOT_FOUND == nErrorCode);
        return CStringA();
    }

    for (auto wszVersion : g_Versions)
    {
        for (const auto &RootDescritption : g_Roots)
        {
            CString csDbgHelpPath;
            ULONG nChars = MAX_PATH;

            nErrorCode = 
                hInstalledRoots.QueryStringValue(
                    CString(RootDescritption.m_wszKeyName) + wszVersion,
                    csDbgHelpPath.GetBuffer(nChars),
                    &nChars);
            if (ERROR_SUCCESS != nErrorCode)
            {
                _ASSERT(ERROR_FILE_NOT_FOUND == nErrorCode);
                csDbgHelpPath.ReleaseBuffer();
                continue;
            }

            _ASSERT(nChars);
            if (!nChars)
            {
                csDbgHelpPath.ReleaseBuffer();
                continue;
            }

            csDbgHelpPath.ReleaseBuffer(nChars - 1);

            CPathA DbgHelpPath = CStringA(csDbgHelpPath);
            DbgHelpPath.Append(RootDescritption.m_szPathTail);
#ifdef  _M_IX86
            DbgHelpPath.Append("x86");
#else   // _M_IX86
#error Unsupported plathorm!
#endif  // _M_IX86

            CPathA DbgHelpFullFileName = DbgHelpPath;
            DbgHelpFullFileName.Append(CDbgHelp::GetLibraryFileName());

            const auto Attributes = ::GetFileAttributesA(DbgHelpFullFileName);
            if ((Attributes != INVALID_FILE_ATTRIBUTES) && 
                !(Attributes & FILE_ATTRIBUTE_DIRECTORY))
            {
                return DbgHelpPath;
            }
        }
    }

    return CStringA();
}

// ----------------------------------------------------------------------------

}   // namespace DSymLoad

// ----------------------------------------------------------------------------
